/*
 * Database access layer
 * Based on: https://github.com/alixaxel/ArrestDB
 * Dani Crespo (C) 2014
 *
 * v 1.0.3 30/08/2014
 */

// Configure base URl for ArrestSQL
//var base_db_uri = "http://diadatest.com/index.php";
//var base_db_uri = "http://db.disier.com";
var base_db_uri = "http://db.diadalocal.com/index.php";

// Esta variable en vez de global tendria que ser un miembro de Db(), pero para buscar errorers de momento es mejor asi
var RETRIEVED_DATA = null;

function Db() {

    // Configura HTTP auth parameters
    this.HTTP_USER = 'apirest';
    this.HTTP_PASSWORD = 'apirest';

    // Set constant for call tye
    this.DB_CREATE = "POST"; // POST   /table
    this.DB_READ = "GET"; // GET    /table[/id]
    this.DB_UPDATE = "PUT"; // PUT    /table/id
    this.DB_DELETE = "DELETE"; // DELETE /table/id

    
    this.dbCall = function(callType, tableName, id, callbackFunction, postData, filterColumn, filterValue, filterList, Synchronous, Offset, Limit, OnlyCounter, OrderColumn, Order) {
        comaLog('Executed dbCall(callType: ' + callType + ', tableName: ' + tableName + ', id: ' + id + ', callbackFunction: ' + (callbackFunction != null ? eval('callbackFunction.name') : 'null') + ', postData: ' + postData + ', filterColumn: ' + filterColumn + ', filterValue: ' + filterValue + ', filterList: ' + filterList + ', Synchronous: ' + Synchronous + ', Offset: ' + Offset + ', Limit: ' + Limit + ', OnlyCounter: ' + OnlyCounter + ')');

        var url;

        // Check if perfmorming a search by id select
        if (id == null) {
            url = base_db_uri + '/' + tableName + '/';
        } else {
            // TODO check id is a number
            url = base_db_uri + '/' + tableName + '/' + id;
        }

        // Check if filtering by a special column
        if (filterColumn != null) {
            url += '?filter_field=' + filterColumn + '&filter_value=' + filterValue;
        }

        // Check if using a list of filters
        if (filterList != null && filterList != '') {
            url += '?filters={' + filterList.join() + '}';
        }

        if (Offset != null && Limit != null && OnlyCounter != true)
            url += '&limit=' + Limit + '&offset=' + Offset;

        if (OnlyCounter)
            url += '&counter=1';

        if (OrderColumn != null && Order != null)
            url += '&order_by=' + OrderColumn + '&order=' + Order;

        console.log("Quering the url: " + url);

        // Switch to synchronous mode 
        if (Synchronous != null && Synchronous == true) {
            //console.log('Entering synchronous mode');
            jQuery.ajaxSetup({
                async: false
            });

            $.ajax({
                type: callType,
                dataType: 'json',
                url: url,
                data: postData,
                username: this.HTTP_USER,
                password: this.HTTP_PASSWORD,
                crossDomain: true,
            })
                .done(function (data, status) {
                    //comaLog(JSON.stringify(data));
                    RETRIEVED_DATA = data;
                    // Error check
                    if (data != null && data.error != null) {
                        switch (data.error.code) {
                        case 404:
                            throw new Error('No se ha podido acceder a la información de base de datos. El elemento no existe');
                            break;
                        case 204:
                            // No content: no error
                            break;
                        case 401:
                            throw new Error('Existe un problema de credenciales para acceder a la base de datos');
                            break;
                        default:
                            throw new Error('Hubo un error realizando la operacion de base de datos. Código: ' + data.error.code + '. Mensaje: ' + data.error.message);
                        }
                    }
                })
                .fail(function (xhr, textStatus, errorThrown) {
                    console.log("ERROR PERFORMING QUERY: " + errorThrown);
                    console.log("Status: " + textStatus);
                    console.log("Response: " + xhr);
                    if (xhr.responseText != null && (xhr.responseText.indexOf('refused') > -1 || xhr.responseText.indexOf('rechazada') > -1))
                        errorThrown = 'La base de datos rechazó la conexión. Compruebe si se encuentra arrancada';
                    throw new Error('Error: ' + errorThrown + '.<br/><br/> Estado: ' + textStatus + '. <br/><br/>Detalle adicional: ' + xhr.responseText);
                });

            // Switch back to asynchronous mode 
            //console.log('Exiting synchronous mode');
            jQuery.ajaxSetup({
                async: true
            });

            return (RETRIEVED_DATA);
        } else // Normal asynchronous mode
        {
            $.ajax({
                type: callType,
                dataType: 'json',
                url: url,
                data: postData,
                username: this.HTTP_USER,
                password: this.HTTP_PASSWORD,
                crossDomain: true,
                xhrFields: {
                    withCredentials: false
                }
            })
                .done(function (data, status) {
                    //comaLog(JSON.stringify(data));
                    RETRIEVED_DATA = data;
                    // Error check
                    if (data != null && data.error != null) {
                        switch (data.error.code) {
                        case 404:
                            throw new Error('No se ha podido acceder a la información de base de datos. El elemento no existe');
                            break;
                        case 204:
                            // No content: no error
                            break;
                        case 401:
                            throw new Error('Existe un problema de credenciales para acceder a la base de datos');
                            break;
                        default:
                            throw new Error('Hubo un error realizando la operacion de base de datos. Código: ' + data.error.code + '. Mensaje: ' + data.error.message);
                        }
                    }
                    callbackFunction();
                })
                .fail(function (xhr, textStatus, errorThrown) {
                    console.log("ERROR PERFORMING QUERY: " + errorThrown);
                    console.log("Status: " + textStatus);
                    console.log("Response: " + xhr.responseText);
                    errorMessage('Error procesando petición', 'Hubo un problema procesando datos de la base de datos', 'Error: ' + errorThrown + '.<br/><br/> Estado: ' + textStatus + '. <br/><br/>Detalle adicional: ' + xhr.responseText);
                });
        }
    };


    /**
     * Performs a query on the database
     * @param {string} tableName . as 'ficha' or 'cliente'
     * @param {integer} id. If we are searching forma aparticular element, it's ID. Use null to perform a query
     * @param {Type} callback
     * @param {Type} filterColumn
     * @param {Type} filterValue
     * @param {Type} filterList
     * @param {Type} Synchronous
     * @param {Type} Offset
     * @param {Type} Limit
     * @param {Type} OnlyCounter
     */
    this.dbSelect = function(tableName, id, callback, filterColumn, filterValue, filterList, Synchronous, Offset, Limit, OnlyCounter, OrderColumn, Order) {
        this.dbCall(this.DB_READ, tableName, id, callback, null, filterColumn, filterValue, filterList, Synchronous, Offset, Limit, OnlyCounter, OrderColumn, Order);
    };


    this.dbUpdate = function(tableName, object, callback) {
        if (object.id == null || object.id == '-1' || object.id == '') {
            delete object.id;
            this.dbCall(this.DB_CREATE, tableName, null, callback, object);
        } else {
            this.dbCall(this.DB_UPDATE, tableName, object.id, callback, object);
        }
    };

    this.dbUpdateSynch = function(tableName, object, callback) {
        if (object.id == null || object.id == '-1' || object.id == '') {
            delete object.id;
            this.dbCall(this.DB_CREATE, tableName, null, callback, object, null, null, null, true);
        } else {
            this.dbCall(this.DB_UPDATE, tableName, object.id, callback, object, null, null, null, true);
        }
    };

    this.dbDelete = function(tableName, id, callback) {
        this.dbCall(this.DB_DELETE, tableName, id,  callback);
    };

    this.dbDeleteSynch = function(tableName, id) {
        this.dbCall(this.DB_DELETE, tableName, id,  null, null, null, null, null, true);
    };

    this.dbInsert = function(tableName, object, callback) {
        this.dbCall(this.DB_CREATE, tableName, null, callback, object);
    };

    this.dbInsertSynch = function(tableName, object, callback) {
        this.dbCall(this.DB_CREATE, tableName, null, callback, object, null, null, null, true);
    };

    /**
     * This functions performs a msql select in synchronous mode. The results are trurned on the function
     */
    this.dbSelectSynch = function(tableName, id) {
        return this.dbCall(this.DB_READ, tableName, id, null, null, null, null, null, true);
    };

    /**
     * Synchornous call to get the total elements on the server
     */
    this.getElementsCount = function(tablename, filterList) {
        return this.dbCall(this.DB_READ, tablename, null, null, null, null, null, filterList, true, null, null, true);
    };
}